package geral.manager;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.Serializable;
import java.sql.Connection;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import javax.enterprise.context.ConversationScoped;
import javax.faces.context.FacesContext;
import javax.inject.Inject;
import javax.inject.Named;
import javax.naming.InitialContext;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.sql.DataSource;

import net.sf.jasperreports.engine.JasperExportManager;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;

@Named
@ConversationScoped
public class RelatorioManager extends GenericManager implements Serializable {

	private static final long serialVersionUID = 7768212376532611764L;

	private String saida;
	private String retorno;
	
	@Inject private UtilManager utilManager;

	public void geraRelatorio(List<?> lista,String jasper, Map<String, Object> map, String fileName) {

		jasper = getDiretorioReal("/jasper/"+jasper);
		saida = getDiretorioReal("/relatorios/relatorio.pdf");
		JRBeanCollectionDataSource ds = new JRBeanCollectionDataSource(lista);
		printReport(fileName, jasper, map, ds);
	}

	public String geraRelatorio(String fileName, String jasper, Map<String, Object> map) {

		jasper = getDiretorioReal("/jasper/"+jasper);
		saida = getDiretorioReal("/relatorios/relatorio.pdf");
		Connection ds;
		try {
			ds = getConnection("sgc");
			printReport(fileName, jasper, map, ds);
		} catch (Exception e) {
			e.printStackTrace();
		} 
		
		return retorno;
	}

	
	private void printReport(String fileName, String jasper, Map<String, Object> map, JRBeanCollectionDataSource ds) {
		try {
			map = createMap(map);
			JasperPrint print = JasperFillManager.fillReport(jasper, map, ds);
			byte[] bytes = JasperExportManager.exportReportToPdf(print);
			forceDownload(fileName, bytes);
		} catch (Exception e) {
			System.out.println(e.getMessage());
		}
	}

	private void printReport(String fileName, String jasper, Map<String, Object> map, Connection ds) {
		try {
			map = createMap(map);
			JasperPrint print = JasperFillManager.fillReport(jasper, map, ds);
			byte[] bytes = JasperExportManager.exportReportToPdf(print);
			forceDownload(fileName, bytes);


		} catch (Exception e) {
			System.out.println(e.getMessage());
		}
	}

	private Map<String, Object> createMap(Map<String, Object> map) {
		if(map == null ) {
			map = new HashMap<String, Object>();
		}
		
		map.put("image", new ByteArrayInputStream(utilManager.getSegurancaManager().getUsuarioLogado().getClinica().getLogotipo()));
		map.put("REPORT_LOCALE",new Locale("pt","BR"));
		return map;
	}

	private String getDiretorioReal(String diretorio) {
		HttpSession session = (HttpSession) FacesContext.getCurrentInstance().getExternalContext().getSession(false);
		return session.getServletContext().getRealPath(diretorio);
	}

	private static Connection getConnection(String dataSource) throws Exception{
		InitialContext context = new InitialContext();
		DataSource ds = (DataSource) context.lookup("jdbc/"+ dataSource);
		return ds.getConnection();
		
	}
	
	private void forceDownload(String fileName, byte[] pdfData) throws IOException{
		FacesContext facesContext = FacesContext.getCurrentInstance();  
	    HttpServletResponse response = (HttpServletResponse) facesContext.getExternalContext().getResponse();  
	    response.setHeader("Content-Disposition", "attachment; filename=\""+fileName + "\";");  
	    response.setContentType("application/force-download");  
	    OutputStream output = response.getOutputStream();
	    output.write(pdfData);
	    output.close();
	    FacesContext.getCurrentInstance().responseComplete();  
	}  
		

	public String getSaida() {
		return saida;
	}

	public void setSaida(String saida) {
		this.saida = saida;
	}

	public String getRetorno() {
		return retorno;
	}

	public void setRetorno(String retorno) {
		this.retorno = retorno;
	}
}
